package com.levi.distributedsession.controller;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.levi.distributedsession.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.UUID;

import static com.levi.distributedsession.interceptor.TokenInterceptor.*;

@RestController
@Slf4j
public class Controller {
    @Autowired
    private RedisUtil redisUtil;

    @GetMapping("hello")
    public String hello() {
        return "hello";
    }
//-------------------spring session----------------------------------
    /**
     * 普通设置session的方式   session.setAttribute()
     * 引入spring session的依赖之后，自动把session存入redis中，从redis中读取判断是否已经登陆过
     * @param username
     * @param password
     * @param session
     * @return
     */
    @GetMapping("login")
    public Object login(@RequestParam String username,
                       String password,
                      HttpSession session){
        /**
         * setAttribute做了两个操作
         * 1.把session保存到服务器内存中
         * 2.setCookie设置cookie把cookie保存到浏览器中，cookie存放的是sessionId
         */
        session.setAttribute("user",username);
        return "登录成功";
    }

    /**
     * 普通获取session的方式
     * 引入spring session的依赖之后，spring
     * @param session
     * @return
     */
    @GetMapping("getUser")
    public Object getUser(HttpSession session) {
        return session.getAttribute("user");
    }

    /**
     * springsession 退出登录
     */
    @GetMapping("logout")
    public void logout(HttpSession session,Long userId) {
        session.removeAttribute("user");
        log.info("session清空，退出登录");
    }
//-----------------------token + redis--------------------
    /**
     * token+redis方式
     * @param username
     * @param password
     * @return
     */
    @GetMapping("loginWithToken")
    public String loginWithToken(@RequestParam String username,
                                 String password) {
        String token = UUID.randomUUID().toString();
        redisUtil.set("token_"+token, username);
        return "token_"+token;
    }

    /**
     * token+redis方式
     * 从redis中获取token
     * @param token
     * @return
     */
    @GetMapping("getUserWithToken")
    public String getUserWithToken(@RequestParam String token) {
        return "username: "+redisUtil.get(token);
    }


    /**
     * 前端把token放进header里面，后端从header里面获取session
     * @param token
     * @return
     */
    @GetMapping("getTokenFromHeader")
    public String getTokenFromHeader(@RequestHeader String token) {

        return "usernane: "+redisUtil.get(token);
    }

    /**
     * 通过jwt生成加密后的token   加密
     * 一般根据用户名，用户id,权限生成jwt 存放在浏览器的storage里面  前端传到后端之后解析jwt获取数据，然后验证
     * @return
     */
    @GetMapping("loginWithJwt")
    public String loginWithJwt(@RequestParam String username,
                               @RequestParam String password) {
        Algorithm algorithm = Algorithm.HMAC256(JWT_KEY);
        //生成token的值不能被篡改，篡改之后无效
        String token = JWT.create()
                //放权限
                .withIssuer("auth0")
                //把用户信息放进   payload  中 可以放多个值，键值对形式，放的值越多，生成的token就越长
                .withClaim(USERNAME, username)
                .withClaim(UID, "123456")
                //设置token过期时间单位是毫秒  为3600秒后过期
                .withExpiresAt(new Date(System.currentTimeMillis() + 3600000))
                .sign(algorithm);
        return token;
    }

    /**
     * 验证jwt生成的token  并且获取token中username   方法在拦截器里面
     * @param username
     * @return
     */
    @GetMapping("/getUserWithJwt")
    public String getUserWithJwt(@RequestAttribute String username) {
        return username;
    }

    /**
     * 验证jwt生成的token, 拦截器拦截后 获取uid  方法在拦截器里面
     * @param uid
     * @return
     */
    @GetMapping("/getUid")
    public String getAddress(@RequestAttribute String uid) {
        return uid;
    }
}
